﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SharpSoft.Data
{
    using System.Reflection;
    /// <summary>
    /// 字段描述
    /// </summary>
    public class FieldDescriptor
    {
        public FieldDescriptor(PropertyInfo propertyInfo)
        {
            if (propertyInfo == null)
            {
                throw new ArgumentNullException(nameof(propertyInfo));
            }
            this.Property = propertyInfo;
            if (!propertyInfo.CanRead)
            {
                throw new Exception("不可读的属性不能用于描述数据字段。");
            }
            if (!propertyInfo.CanWrite)
            {//只读属性
                ForInsert = false;
                ForUpdate = false;
                ForSelect = false;
            }

            var aa = propertyInfo.GetCustomAttribute<AutoFieldAttribute>();
            if (aa != null)
            {
                this.IsAuto = true;
                this.ForInsert = false;//自增字段不用于插入也不更新
                this.ForUpdate = false;
            }

            var pka = propertyInfo.GetCustomAttribute<PrimaryKeyAttribute>();
            if (pka != null)
            {
                this.IsPrimaryKey = true;
                this.ForUpdate = false;//主键不更新
            }
            var mpa = propertyInfo.GetCustomAttribute<MappingNameAttribute>();
            if (mpa != null)
            {
                this.MappingName = mpa.Name;
            }
            var va = propertyInfo.GetCustomAttribute<VirtualFieldAttribute>();
            if (va != null)
            {
                this.IsVirtual = true;
                this.ForSelect = false;
            }
            var jia = propertyInfo.GetCustomAttribute<JoinInsertAttribute>();
            if (jia != null)
            {
                this.ForInsert = true;
            }
            var jua = propertyInfo.GetCustomAttribute<JoinUpdateAttribute>();
            if (jua != null)
            {
                this.ForUpdate = true;
            }
            var djia = propertyInfo.GetCustomAttribute<DontJoinInsertAttribute>();
            if (djia != null)
            {
                this.ForInsert = false;
            }
            var djua = propertyInfo.GetCustomAttribute<DontJoinUpdateAttribute>();
            if (djua != null)
            {
                this.ForUpdate = false;
            }
            var fka = propertyInfo.GetCustomAttribute<ForeignKeyAttribute>();
            if (fka != null)
            {
                this.ForeignKey = new ForeignKeyDescriptor(fka);
            }
            var cqa = propertyInfo.GetCustomAttribute<CustomQueryAttribute>();
            if (cqa != null)
            {//自定义了查询语句的字段强制不再用于插入、更新、查询
                this.ForInsert = false;
                this.ForSelect = false;
                this.ForUpdate = false;
                this.CustomQueryCommandString = cqa.QueryString;
            }
            var dna = propertyInfo.GetCustomAttribute<System.ComponentModel.DisplayNameAttribute>();
            if (dna != null)
            {
                this.DisplayName = dna.DisplayName;
            }
            var da = propertyInfo.GetCustomAttribute<System.ComponentModel.DescriptionAttribute>();
            if (da != null)
            {
                this.Description = da.Description;
            }
        }
        /// <summary>
        /// 关联到的属性
        /// </summary>
        public PropertyInfo Property { get; private set; }
        /// <summary>
        /// 是否为自增字段
        /// </summary>
        public bool IsAuto { get; set; } = false;
        /// <summary>
        /// 是否为主键
        /// </summary>
        public bool IsPrimaryKey { get; private set; } = false;
        /// <summary>
        /// 是否为虚字段
        /// </summary>
        public bool IsVirtual { get; private set; } = false;
        /// <summary>
        /// 映射名称
        /// </summary>
        public string MappingName { get; set; }
        /// <summary>
        /// 当前字段是否需要插入数据库
        /// </summary>
        public bool ForInsert { get; private set; } = true;
        /// <summary>
        /// 当前字段是否需要更新到数据库
        /// </summary>
        public bool ForUpdate { get; set; } = true;
        /// <summary>
        /// 当前字段是否需要从数据库查询
        /// </summary>
        public bool ForSelect { get; set; } = true;
        /// <summary>
        /// 显示名称
        /// </summary>
        public string DisplayName { get; private set; }
        /// <summary>
        /// 描述信息
        /// </summary>
        public string Description { get; private set; }
        /// <summary>
        /// 为字段自定义查询语句
        /// </summary>
        public string CustomQueryCommandString { get; private set; }


        /// <summary>
        /// 关联的外键信息
        /// </summary>
        public ForeignKeyDescriptor ForeignKey { get; private set; }
        /// <summary>
        /// 是否为外键
        /// </summary>
        public bool IsForeignKey { get => ForeignKey != null; }
        /// <summary>
        /// 获取当前字段在数据库中使用的名称
        /// </summary>
        /// <returns></returns>
        public string GetNameInDb()
        {
            if (!string.IsNullOrEmpty(MappingName))
            {//指定了映射名称
                return this.MappingName;
            }
            if (Property.IsSpecialName)
            {
                return Property.Name.TrimStart('@');//去掉特殊名称前面的“@”符号
            }
            return Property.Name;
        }
        /// <summary>
        /// 获取属性名称，如果属性名是以@开头的特殊名称则去掉@。
        /// </summary>
        /// <returns></returns>
        public string GetPropertyName()
        {
            if (Property.IsSpecialName)
            {
                return this.Property.Name.TrimStart('@');
            }
            return this.Property.Name;
        }
    }
}
